import { Profile } from 'mixly';
import mustache from 'mustache';

import TEMPLATE_VARIABLE_IR_PROTOCOL_TYPE from '../templates/cpp/variable-ir-protocol-type.cpp';
import TEMPLATE_LOOP_IR_RECV from '../templates/cpp/loop-ir-recv.cpp';

export const ir_recv = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var branch = generator.statementToCode(this, 'DO');
    var branch2 = generator.statementToCode(this, 'DO2');
    generator.definitions_['include_IRremote'] = '#include <IRremote.h>\n';
    generator.definitions_['var_declare_irProtocolList'] = TEMPLATE_VARIABLE_IR_PROTOCOL_TYPE;
    generator.definitions_['var_declare_irrecv_' + dropdown_pin] = `IRrecv irrecv_${dropdown_pin}(${dropdown_pin});\n`;
    generator.setups_['setup_ir_recv_' + dropdown_pin] = `irrecv_${dropdown_pin}.enableIRIn();`;
    var code = mustache.render(TEMPLATE_LOOP_IR_RECV, {
        pin: dropdown_pin,
        branch, branch2
    });
    return code;
}

export const ir_recv_enable = function (_, generator) {
    generator.definitions_['include_IRremote'] = '#include <IRremote.h>';
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    var code = 'irrecv_' + dropdown_pin + '.enableIRIn();\n';
    return code;
}

export const ir_send_nec = function (_, generator) {
    generator.definitions_['include_IRremote'] = '#include <IRremote.h>\n';
    generator.definitions_['var_declare_ir_send'] = 'IRsend irsend;\n';
    var data = generator.valueToCode(this, 'data', generator.ORDER_ATOMIC) || '0';
    var bits = generator.valueToCode(this, 'bits', generator.ORDER_ATOMIC) || '0';
    var type = this.getFieldValue('TYPE');
    var code = 'irsend.send' + type + '(' + data + ',' + bits + ');\n';
    return code;
}

import TEMPLATE_FUNCTION_DUMP_RAW from '../templates/cpp/function-dump-raw.cpp';

export const ir_recv_raw = function (_, generator) {
    var dropdown_pin = generator.valueToCode(this, 'PIN', generator.ORDER_ATOMIC);
    generator.definitions_['include_IRremote'] = '#include <IRremote.h>';
    generator.definitions_['function_dumpRaw'] = TEMPLATE_FUNCTION_DUMP_RAW;
    generator.definitions_['var_declare_ir_recv' + dropdown_pin] = 'IRrecv irrecv_' + dropdown_pin + '(' + dropdown_pin + ');\ndecode_results results_' + dropdown_pin + ';\n';
    if (!generator.setups_['setup_serial_Serial']) {
        generator.setups_['setup_serial_Serial'] = 'Serial.begin(' + Profile.default.serial + ');';
    }
    generator.setups_['setup_ir_recv_' + dropdown_pin] = 'irrecv_' + dropdown_pin + '.enableIRIn();\n';
    var code = "if (irrecv_" + dropdown_pin + ".decode(&results_" + dropdown_pin + ")) {\n"
    code += '  ' + 'dumpRaw(&results_' + dropdown_pin + ');\n';
    code += '  irrecv_' + dropdown_pin + '.resume();\n'
    code += '}\n';
    return code;
}

export const ir_send_raw = function (_, generator) {
    generator.definitions_['include_IRremote'] = '#include <IRremote.h>\n';
    generator.definitions_['var_declare_ir_send'] = 'IRsend irsend;\n';
    var length = generator.valueToCode(this, 'length', generator.ORDER_ATOMIC) || '0';
    var freq = generator.valueToCode(this, 'freq', generator.ORDER_ATOMIC) || '0';
    var text = this.getFieldValue('TEXT');
    var code = 'unsigned int buf_raw[' + length + ']={' + text + '};\n'
    code = code + 'irsend.sendRaw(buf_raw,' + length + ',' + freq + ');\n';
    return code;
}

export const i2c_master_writer = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    var device = generator.valueToCode(this, 'device', generator.ORDER_ATOMIC) || '0';
    var value = generator.valueToCode(this, 'value', generator.ORDER_ATOMIC) || '0';
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var code = dropdown_i2c_type + ".beginTransmission(" + device + ");\n";
    code += dropdown_i2c_type + ".write((uint8_t)" + value + ");\n";
    code += dropdown_i2c_type + ".endTransmission();\n";
    return code;
}

export const i2c_master_reader2 = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var code = dropdown_i2c_type + ".read()";
    return [code, generator.ORDER_ATOMIC];
}

// YANG add slave write
export const i2c_slave_write = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var value = generator.valueToCode(this, 'value', generator.ORDER_ATOMIC) || '0';
    var code = dropdown_i2c_type + ".write((uint8_t)" + value + ");\n";
    return code;
}

//IIC主机初始化
export const i2c_master_Init = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    if (dropdown_i2c_type != 'remap_I2C_1') {
        generator.setups_['setup_i2c_' + dropdown_i2c_type] = dropdown_i2c_type + '.begin();';
    }
    else {
        generator.setups_['setup_i2c_remap_I2C_1'] = 'afio_remap(AFIO_REMAP_I2C1);\n'
            + '  gpio_set_mode(GPIOB, 9, GPIO_AF_OUTPUT_OD);\n'
            + '  gpio_set_mode(GPIOB, 8, GPIO_AF_OUTPUT_OD);';
        generator.setups_['setup_i2c_Wire'] = 'Wire.begin();';
    }
    var code = '';
    return code;
}

//IIC从机初始化
export const i2c_slave_Init = function (_, generator) {
    var value_i2c_address = generator.valueToCode(this, 'i2c_address', generator.ORDER_ATOMIC);
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    if (dropdown_i2c_type != 'remap_I2C_1') {
        generator.setups_['setup_i2c_' + dropdown_i2c_type] = dropdown_i2c_type + '.begin(' + value_i2c_address + ');';
    }
    else {
        generator.setups_['setup_i2c_remap_I2C_1'] = 'afio_remap(AFIO_REMAP_I2C1);\n'
            + '  gpio_set_mode(GPIOB, 9, GPIO_AF_OUTPUT_OD);\n'
            + '  gpio_set_mode(GPIOB, 8, GPIO_AF_OUTPUT_OD);';
        generator.setups_['setup_i2c_Wire'] = 'Wire.begin(' + value_i2c_address + ');';
    }
    var code = '';
    return code;
}

//IIC发送数据
export const i2c_begin_end_transmission = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var value_i2c_address = generator.valueToCode(this, 'i2c_address', generator.ORDER_ATOMIC);
    var statements_transmission_data = generator.statementToCode(this, 'transmission_data');
    var code = dropdown_i2c_type + '.beginTransmission(' + value_i2c_address + ');\n'
        + statements_transmission_data
        + dropdown_i2c_type + '.endTransmission();\n';
    return code;
}

//IIC写入数据
export const i2c_write = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var value_i2c_write_data = generator.valueToCode(this, 'i2c_write_data', generator.ORDER_ATOMIC);
    var code = dropdown_i2c_type + '.write((uint8_t)' + value_i2c_write_data + ');\n';
    return code;
}

export const i2c_slave_write_array = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var array = generator.valueToCode(this, 'array', generator.ORDER_ATOMIC);
    var length = generator.valueToCode(this, 'length', generator.ORDER_ATOMIC) || '1';
    var code = dropdown_i2c_type + ".write(" + array + "," + length + ");\n";
    return code;
}

export const i2c_available = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var code = dropdown_i2c_type + ".available()";
    return [code, generator.ORDER_ATOMIC];
}

//IIC读取数据
export const i2c_read = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    var code = dropdown_i2c_type + ".read()";
    return [code, generator.ORDER_ATOMIC];
}

//寄存器读写
export const i2c_master_writerReg = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var device = generator.valueToCode(this, 'device', generator.ORDER_ATOMIC) || '0';
    var regadd = generator.valueToCode(this, 'regadd', generator.ORDER_ATOMIC) || '0';
    var value = generator.valueToCode(this, 'value', generator.ORDER_ATOMIC) || '0';
    var code = dropdown_i2c_type + ".beginTransmission(" + device + ");\n";
    code += dropdown_i2c_type + ".write((uint8_t)" + regadd + ");\n";
    code += dropdown_i2c_type + ".write((uint8_t)" + value + ");\n";
    code += dropdown_i2c_type + ".endTransmission();\n";
    return code;
}

export const i2c_master_readerReg = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var device = generator.valueToCode(this, 'device', generator.ORDER_ATOMIC) || '0';
    var regadd = generator.valueToCode(this, 'regadd', generator.ORDER_ATOMIC) || '0';
    var bytes = generator.valueToCode(this, 'bytes', generator.ORDER_ATOMIC) || '0';
    var code = dropdown_i2c_type + ".beginTransmission(" + device + ");\n";
    code += dropdown_i2c_type + ".write((uint8_t)" + regadd + ");\n";
    code += dropdown_i2c_type + ".requestFrom(" + device + ", " + bytes + ");\n";
    code += dropdown_i2c_type + ".endTransmission();\n";
    return code;
}

export const i2c_slave_onreceive = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var value_onReceive_length = generator.valueToCode(this, 'onReceive_length', generator.ORDER_ATOMIC);
    var statements_i2c_onReceive_data = generator.statementToCode(this, 'DO');
    generator.definitions_['function_receiveEvent_' + dropdown_i2c_type] = 'void receiveEvent_' + dropdown_i2c_type + '(int ' + value_onReceive_length + ')'
        + '\n{'
        + '  ' + statements_i2c_onReceive_data
        + '\n}\n'
    generator.setups_['setup_i2c_receiveEvent_' + dropdown_i2c_type] = dropdown_i2c_type + '.onReceive(receiveEvent_' + dropdown_i2c_type + ');';
    var code = '';
    return code;
}

export const i2c_slave_onrequest = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    generator.setups_['setup_i2c_onRequest_' + dropdown_i2c_type] = dropdown_i2c_type + '.onRequest(RequestEvent_' + dropdown_i2c_type + ');';
    var funcName = 'RequestEvent_' + dropdown_i2c_type;
    var branch = generator.statementToCode(this, 'DO');
    var code2 = 'void' + ' ' + funcName + '() {\n' + branch + '}\n';
    generator.definitions_[funcName] = code2;
    return '';
}

export const i2c_master_reader = function (_, generator) {
    var dropdown_i2c_type = this.getFieldValue('i2c_type');
    generator.definitions_['include_Wire_slave'] = '#include <Wire_slave.h>';
    var device = generator.valueToCode(this, 'device', generator.ORDER_ATOMIC) || '0';
    var bytes = generator.valueToCode(this, 'bytes', generator.ORDER_ATOMIC) || '0';
    var code = dropdown_i2c_type + ".requestFrom(" + device + ", " + bytes + ");\n";
    return code;
}

export const spi_begin_master = function (_, generator) {
    var value_spi_slave_pin = generator.valueToCode(this, 'spi_slave_pin', generator.ORDER_ATOMIC);
    var dropdown_spi_type = this.getFieldValue('spi_type');
    generator.definitions_['include_SPI'] = '#include <SPI.h>';
    if (dropdown_spi_type != 'remap_SPI_1') {
        generator.definitions_['var_declare_' + dropdown_spi_type] = 'SPIClass ' + dropdown_spi_type + '(' + dropdown_spi_type.charAt(dropdown_spi_type.length - 1) + ');';
        generator.setups_['setup_spi_' + dropdown_spi_type] = dropdown_spi_type + '.begin();\n'
            + '  ' + dropdown_spi_type + '.setBitOrder(MSBFIRST);\n'
            + '  ' + dropdown_spi_type + '.setDataMode(SPI_MODE0);\n'
            + '  ' + dropdown_spi_type + '.setClockDivider(SPI_CLOCK_DIV16);\n'
            + '  ' + 'pinMode(' + value_spi_slave_pin + ', OUTPUT);';
    }
    else {
        generator.definitions_['var_declare_SPI_1'] = 'SPIClass SPI_1(1);';
        generator.setups_['setup_spi_remap_SPI_1'] = 'afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY);\n'
            + '  afio_remap(AFIO_REMAP_SPI1);\n'
            + '  gpio_set_mode(GPIOB, 3, GPIO_AF_OUTPUT_PP);\n'
            + '  gpio_set_mode(GPIOB, 4, GPIO_INPUT_FLOATING);\n'
            + '  gpio_set_mode(GPIOB, 5, GPIO_AF_OUTPUT_PP);';
        generator.setups_['setup_spi_SPI_1'] = 'SPI_1.begin();\n'
            + '  SPI_1.setBitOrder(MSBFIRST);\n'
            + '  SPI_1.setDataMode(SPI_MODE0);\n'
            + '  SPI_1.setClockDivider(SPI_CLOCK_DIV16);\n'
            + '  pinMode(' + value_spi_slave_pin + ', OUTPUT);';
    }
    var code = '';
    return code;
}

//SPI 初始化从机
export const spi_begin_slave = function (_, generator) {
    var dropdown_spi_type = this.getFieldValue('spi_type');
    generator.definitions_['include_SPI'] = '#include <SPI.h>';
    if (dropdown_spi_type != 'remap_SPI_1') {
        generator.definitions_['var_declare_' + dropdown_spi_type] = 'SPIClass ' + dropdown_spi_type + '(' + dropdown_spi_type.charAt(dropdown_spi_type.length - 1) + ');';
        generator.setups_['setup_spi_' + dropdown_spi_type] = dropdown_spi_type + '.beginTransactionSlave(SPISettings(18000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT));';
    }
    else {
        generator.definitions_['var_declare_SPI_1'] = 'SPIClass SPI_1(1);';
        generator.setups_['setup_spi_remap_SPI_1'] = 'afio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY);\n'
            + '  afio_remap(AFIO_REMAP_SPI1);\n'
            + '  gpio_set_mode(GPIOB, 3, GPIO_AF_OUTPUT_PP);\n'
            + '  gpio_set_mode(GPIOB, 4, GPIO_INPUT_FLOATING);\n'
            + '  gpio_set_mode(GPIOB, 5, GPIO_AF_OUTPUT_PP);';
        generator.setups_['setup_spi_SPI_1'] = 'SPI_1.beginTransactionSlave(SPISettings(18000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT));';

    }
    var code = '';
    return code;
}

export const spi_transfer_Init = function (_, generator) {
    var value_slave_pin = generator.valueToCode(this, 'slave_pin', generator.ORDER_ATOMIC);
    var statements_transfer_data = generator.statementToCode(this, 'transfer_data');
    var code = 'digitalWrite(' + value_slave_pin + ', LOW);\n'
        + statements_transfer_data
        + 'digitalWrite(' + value_slave_pin + ', HIGH);\n';
    return code;
}

export const spi_transfer_1 = function (_, generator) {
    var dropdown_spi_type = this.getFieldValue('spi_type');
    var value_transfer_data = generator.valueToCode(this, 'transfer_data', generator.ORDER_ATOMIC);
    var code = dropdown_spi_type + '.transfer(' + value_transfer_data + ');\n';
    return code;
}

export const spi_transfer_2 = function (_, generator) {
    var dropdown_spi_type = this.getFieldValue('spi_type');
    var value_transfer_data = generator.valueToCode(this, 'transfer_data', generator.ORDER_ATOMIC);
    var code = dropdown_spi_type + '.transfer(' + value_transfer_data + ')';
    return [code, generator.ORDER_ATOMIC];
}